/*
 * @Author: wuqingchun
 * @Date: 2024-05-30 14:42:46
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-07-12 18:12:14
 */

#include <iostream>
#include <mutex>
#include <list>
#include <thread>

#include "spinlock.h"


// 互斥量加不上锁，线程会进入休眠状态
// 自旋锁加不上锁，线程会自选，一直忙等

template <typename T>
class SafeList
{
    struct ListNode
    {
        ListNode* pstNext;
        T tData;

        ListNode(const T& refData)
        {
            pstNext = nullptr;
            tData = refData;
        }
    };
public:
    bool AddHead(const T& refData)
    {
        ListNode* pstNode = new (std::nothrow) ListNode(refData);
        if (pstNode == nullptr)
        {
            return false;
        }

        std::lock_guard<std::mutex> objLG(m_objMtx);    
        if (m_pstHead != nullptr)
        {
            pstNode->pstNext = m_pstHead;
        }

        m_pstHead = pstNode;

        if (m_pstTail == nullptr)
        {
            m_pstTail = pstNode;
        }

        return true;
    }

    bool AddTail(const T& refData)
    {
        ListNode* pstNode = new (std::nothrow) ListNode(refData);
        if (pstNode == nullptr)
        {
            return false;
        }

        std::lock_guard<std::mutex> objLG(m_objMtx);
        if (m_pstTail != nullptr)
        {
            m_pstTail->pstNext = pstNode;
        }

        m_pstTail = pstNode;

        if (m_pstHead == nullptr)
        {
            m_pstHead = pstNode;
        }
    }
    
    bool DeleteHead(T& refData)
    {
        std::lock_guard<std::mutex> objLG(m_objMtx);
    }

    void DeleteTail()
    {

    }

private:
    ListNode* m_pstHead {nullptr};
    ListNode* m_pstTail {nullptr};
    std::mutex m_objMtx;
};


int main()
{
    SafeList<int> objSList;
    
    std::thread objThread1([&](){
        objSList.AddHead(10);
    });
    

    std::thread objThread2([&](){
        objSList.AddHead(10);
    });

    objThread1.join();
    objThread2.join();

    while (1)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}